package com.atguigu.gmall.user.service.impl;

import com.atguigu.gmall.common.constant.RedisConstant;
import com.atguigu.gmall.common.execption.GmallException;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.util.JSONs;
import com.atguigu.gmall.common.util.MD5;
import com.atguigu.gmall.model.user.entity.UserInfo;
import com.atguigu.gmall.model.user.vo.LoginParamsVO;
import com.atguigu.gmall.model.user.vo.LoginResultVO;
import com.atguigu.gmall.user.mapper.UserInfoMapper;
import com.atguigu.gmall.user.service.UserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
* @author jiamin
* @description 针对表【user_info(用户表)】的数据库操作Service实现
* @createDate 2023-08-29 16:37:26
*/
@Service
@Slf4j
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
    implements UserInfoService{

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public LoginResultVO doLogin(LoginParamsVO loginParamsVO, String ipAddress) {
        //判断参数是否为空
        if (loginParamsVO == null) {
            throw new GmallException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (!StringUtils.hasText(loginParamsVO.getLoginName()) || !StringUtils.hasText(loginParamsVO.getPasswd())) {
            throw new GmallException(ResultCodeEnum.PARAMS_ERROR);
        }
        //查询数据库，看用户是否存在
        UserInfo userInfo = lambdaQuery().eq(UserInfo::getLoginName, loginParamsVO.getLoginName())
                .eq(UserInfo::getPasswd, MD5.encrypt(loginParamsVO.getPasswd())).one();
        if (userInfo == null) {
            throw new GmallException(ResultCodeEnum.PARAMS_ERROR);
        }
        //生成一个token
        String token = UUID.randomUUID().toString().replaceAll("-", "") + "_" + userInfo.getId();
        userInfo.setIpAddress(ipAddress);

        //线上是不允许用keys的，keys会造成阻塞，导致一系列问题
//        Set<String> keys = stringRedisTemplate.keys(RedisConstant.REDIS_USER_INFO_PREFIX + "*_" + userInfo.getId());
        String key = findFirstMatchingKey(RedisConstant.REDIS_USER_INFO_PREFIX + "*_" + userInfo.getId());
        if (StringUtils.hasText(key)) {
            //如果登录过，就去数据库删掉上一次的登录
            stringRedisTemplate.delete(key);
        }

        //将数据存到reids
        stringRedisTemplate.opsForValue().set(RedisConstant.REDIS_USER_INFO_PREFIX + token,
                JSONs.objecttoString(userInfo), 7, TimeUnit.DAYS);

        //查看该用户是否在其他地方登录过

        //封装返回结果
        LoginResultVO loginResultVO = new LoginResultVO();
        loginResultVO.setToken(token);
        loginResultVO.setNickName(userInfo.getNickName());
        loginResultVO.setUserId(userInfo.getId());
        loginResultVO.setName(userInfo.getName());
        return loginResultVO;
    }

    public String findFirstMatchingKey(String pattern) {
        return stringRedisTemplate.execute((RedisCallback<String>) connection -> {
            ScanOptions scanOptions = ScanOptions.scanOptions()
                    .match(pattern)
                    .count(1) // 设置一次迭代的数量为1，即找到一个匹配的键就结束
                    .build();
            Cursor<byte[]> cursor = connection.scan(scanOptions);
            if (cursor.hasNext()) {
                return new String(cursor.next());
            }
            return null;
        });
    }
}





